<?php

/* Begin Timer Code */
include_once("inc/Timer.php");
$t = new Timer();
/********************/

include_once("inc/ColumnUsage.php");
include_once("inc/Table.php");
include_once("inc/Column.php");
include_once("inc/ExtArray.php");

$conn = mysql_connect("localhost", "root", "");
$db = "testdb";
mysql_select_db($db);

$tables = new EArray();

// First, gather all tables
$tablesResult = mysql_query("SELECT * FROM information_schema.TABLES WHERE TABLE_SCHEMA = '{$db}';");
while($tableRow = mysql_fetch_assoc($tablesResult))
{
	$table = new Table();
	$table->name = $tableRow["TABLE_NAME"];

	$tables->append($table);
}


// Second, gather all columns in the tables
foreach($tables as $table)
{
	$columnsResult = mysql_query("SELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA='{$db}' AND TABLE_NAME='{$table->name}';");
	
	while($columnRow = mysql_fetch_assoc($columnsResult))
	{
		//$columnName = $row["COLUMN_NAME"];
		$column = new Column();
		$column->name($columnRow["COLUMN_NAME"])
			   ->type($columnRow["DATA_TYPE"])
			   ->size($columnRow["CHARACTER_MAXIMUM_LENGTH"]);

		$table->columns[] = $column;
	}
}

// Third, gather constraints and key usage on the table/columns
foreach($tables as $table)
{
	foreach($table->columns as $column)
	{
		$keyResult = mysql_query("SELECT * FROM information_schema.KEY_COLUMN_USAGE WHERE CONSTRAINT_SCHEMA='{$db}' AND TABLE_NAME='{$table->name}' AND COLUMN_NAME='{$column->name}';");
		if(mysql_num_rows($keyResult) > 0)
		{			
			while($keyRow = mysql_fetch_assoc($keyResult))
			{
				if($keyRow["CONSTRAINT_NAME"] == "PRIMARY")
				{
					$column->isPrimary(true);
				}
				else if($keyRow["CONSTRAINT_NAME"] != "PRIMARY")
				{
					$column->isPrimary(false);

					$refTable = $keyRow["REFERENCED_TABLE_NAME"];
					$refCol = $keyRow["REFERENCED_COLUMN_NAME"];
					$column->has_reference_to($refTable, $tables->where("name", $refTable)->columns()->where("name", $refCol));
				}
			}
		}
	}
}





// Generate database file

$fname = $db . "_db.php";
$fh = fopen($fname, "w+");
$content = "";

$content .= "\n<?php\n\n";
$content .= get_header_info();

$content .= "\ninclude_once(\"inc/Base.php\");\n\n";

foreach($tables as $table)
{
	$content .= "class " . $table->name . " extends Base\n{\n";
	$privateMembers = "";
	$publicAccessors = "";
	$references = "";
	
	foreach($table->columns as $column)
	{
		if($column->isPrimary) {
			//echo "&nbsp;&nbsp;PK: " . $column->name . "<br />";
			$privateMembers .= "\tprivate \$_" . $column->name . ";\t// PK - " . $column->type . "\n";
			$publicAccessors .= "\n\tpublic function " . $column->name . "()\n\t{\n\t\treturn \$this->". $column->name . ";\n\t}\n";
		}
		else {
			
			$privateMembers .= "\tprivate \$_" . $column->name . ";\t// " . prepare_size($column) . "\n";
			$publicAccessors .= get_accessor($column);
			
			if(count($column->references) > 0)	// has references to other tables
			{
				foreach($column->references as $ref)
				{
					$privateMembers .= "\tprivate \$_" . $ref->table . ";\t//". $ref->table ." object\n";
					$references .= get_reference($ref);
				}
			}
		}
	}
		
	$content .= $privateMembers;
	$content .= $publicAccessors;
	$content .= $references;
	$content .= "\n\tpublic function __construct()\n\t{";
	$content .= "\n\t}\n";
	
	$content .= generate_single_statement($table);
	$content .= generate_save($table);
	
	$content .= "}\n\n";

}

$content .= "?>";

fwrite($fh, $content);
fclose($fh);



/**************************************/
function generate_save($table)
{
	return "
	public function save()
	{
		parent::save(\$this);
	}
";
}


function generate_single_statement($table)
{
	$statement = "";
	$statement .= "
	public function single(\$attr, \$val)
	{
		// sql statement to select single element
		\$query = \"SELECT * FROM `{$table->name}` WHERE `\$attr` = '\$val' limit 1;\";
		\$db = new DB();
		\$result = \$db->execute_return(\$query);
		\$result = \$result[0];
";
	
	foreach($table->columns as $column)
	{
		$statement .= "\t\t\$this->_" . $column->name . " = \$result[\"" . $column->name . "\"];\n";
	}
	
	$statement .= "
		return \$this;
	}
";

	return $statement;

}

function get_header_info()
{
	return "/* 
	This is an auto-generated file. Any changes you make will be overwritten on the next generation.
	
	If you would like to incorporate your business rules into the classes below, create a new object and extend
	the desired class.
	
	Ex: If you want to add business rules to a class named \"Test\", do the following:
	class MyTest extends Test
	{
		public \$otherProperties;
		public function OtherMethods() {
			// Stuff in here
		}
	}
	
*/\n\n";
}

function get_reference($reference)
{
	return "
	public function " . $reference->table . "(\$val=null)
	{
		if(\$val == null)	// Getter
		{
			return \$this->". $reference->table ."
		}
		else // Setter
		{
			\$this->". $reference->table ." = \$val;
		}
	}
";
}

function prepare_size($column)
{
	if($column->type == "varchar")
		return $column->type . "(" . $column->size . ")";
	
	return $column->type;
}

function get_accessor($column)
{
	// Determine type
	$typeCode = "";
	switch($column->type)
	{
		case "int":
		{
			$typeCode .= "if(!is_int(\$val))
					throw new InvalidArgumentException(\"Type mismatch. Expected: int, actual: \" . gettype(\$val));";
			break;
		}
		case "varchar":
		{
			$typeCode .= "if(!is_string(\$val))
					throw new InvalidArgumentException(\"Type mismatch. Expected: string, actual: \" . gettype(\$val));";
			break;
		}
		default:
			break;
	}
	
	
	return "
	public function " . $column->name . "(\$val=\"\")
	{
		if(empty(\$val))	// Getter
		{
			return \$this->_" . $column->name . ";
		}
		else			// Setter
		{
			if(\$this->_" . $column->name . " != \$val)
			{
				$typeCode

				\$this->_" . $column->name . "=\$val;
			}
		}
	}
";
}


/* End Timer Code */
$totalTime = round($t->end(), 5);

echo "Created $fname in $totalTime seconds<br /><br />";
$content = str_replace("<", "&lt;", $content);
$content = str_replace(">", "&gt;", $content);
echo "<code><pre>". $content ."</pre></code>";


/********************/


?>